/*
 *  $Id: Image.cs 1199 2010-11-20 17:38:24Z thenn.erannor $
 *	This file is a part of Ragima CCG.
 *	(C) 2008 Ragima development group.
 *
 *	Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Ragima {
    /// <summary>
    /// Вспомогательные методы по работе с изображениями.
    /// </summary>
    public static class ImageHelper {
        /// <summary>
        /// Позиция якоря на изображении: с какой стороны брать его часть, если оно не масштабируется с сохранением пропорций.
        /// </summary>
        public enum AnchorPosition {
            Center,
            Top,
            Bottom,
            Left,
            Right
        }

        /// <summary>
        /// Подготавливает изображение аватара из указанного файла. Возвращает имя файла аватара.
        /// </summary>
        public static string PrepareAvatar(string filename) {
            var image = Crop(filename, Constants.AvatarSize, Constants.AvatarSize, AnchorPosition.Center);
            var data = new MemoryStream();
            image.Save(data, ImageFormat.Jpeg);
            image.Dispose();
            var name = CreateHashName(data);
            data.Position = 0;
            using (var file = new FileStream(Paths.Avatars[name], FileMode.Create)) {
                data.WriteTo(file);
            }
            data.Dispose();
            return name;
        }

        /// <summary>
        /// Создает имя файла по хэш-коду данных.
        /// </summary>
        private static string CreateHashName(Stream data) {
            var x = new MD5CryptoServiceProvider();
            data.Position = 0;
            var hash = x.ComputeHash(data);
            var sb = new StringBuilder(hash.Length * 2 + 5);
            foreach (var b in hash)
                sb.AppendFormat("{0:x}", b);
            sb.Append(".jpg");
            return sb.ToString();
        }

        /// <summary>
        /// Вырезает и масштабирует изображение из указанного файла.
        /// </summary>
        public static Image Crop(string filename, int width, int height, AnchorPosition anchor) {
            var sourceImage = new Bitmap(filename);
            var destImage = Crop(sourceImage, width, height, anchor);
            sourceImage.Dispose();
            return destImage;
        }

        /// <summary>
        /// Вырезает и масштабирует указанное изображение.
        /// </summary>
        public static Image Crop(Image sourceImage, int width, int height, AnchorPosition anchor) {
            int sourceWidth = sourceImage.Width;
            int sourceHeight = sourceImage.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)width/(float)sourceWidth);
            nPercentH = ((float)height/(float)sourceHeight);

            if (nPercentH < nPercentW) {
                nPercent = nPercentW;
                switch (anchor) {
                    case AnchorPosition.Top:
                        destY = 0;
                        break;
                    case AnchorPosition.Bottom:
                        destY = (int) (height - (sourceHeight * nPercent));
                        break;
                    default:
                        destY = (int) ((height - (sourceHeight * nPercent))/2);
                        break;
                }
            } else {
                nPercent = nPercentH;
                switch (anchor) {
                    case AnchorPosition.Left:
                        destX = 0;
                        break;
                    case AnchorPosition.Right:
                        destX = (int) (width - (sourceWidth * nPercent));
                        break;
                    default:
                        destX = (int) ((width - (sourceWidth * nPercent))/2);
                        break;
                } 
            }

            int destWidth  = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap destImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);
            destImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);

            Graphics tempImage = Graphics.FromImage(destImage);
            tempImage.InterpolationMode = InterpolationMode.HighQualityBicubic;

            tempImage.DrawImage(sourceImage, 
                new Rectangle(destX,destY,destWidth,destHeight),
                new Rectangle(sourceX,sourceY,sourceWidth,sourceHeight),
                GraphicsUnit.Pixel);

            tempImage.Dispose();
            return destImage;
        }
    }
}
